import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:base_flutter/common/global.dart';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';

class DioInterceptor extends Interceptor {

  Function(RequestOptions options)? hookOnRequest;
  DioInterceptor({this.hookOnRequest});

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // TODO: implement onRequest

    if (hookOnRequest != null) {
        hookOnRequest!(options);
    }
    if (Platform.isIOS) {
      options.headers["platform"] = "iOS";
    }else if (Platform.isAndroid) {
      options.headers["platform"] = "android";
    }else {
      options.headers["platform"] = "web";
    }
    options.headers["env"] = Global.isRelease ? "Product" : "Develop";
    options.headers["version"] = Global.version;

    /// 添加用户Token
    ///
    if(Global.isLogin) {
      options.headers["Authorization"] = Global.token;
    }
    debugInfo(options.data.runtimeType);
    debugInfo(options.data is Map );
    if (options.data != null && options.data is Map) {

      if(Global.profile.location != null) {
        options.data['lng'] = Global.profile.location?.longitude;
        options.data['lat'] = Global.profile.location?.latitude;
      }else if(!Global.isRelease) {
        options.data['lng'] = '104.168738';
        options.data['lat'] = '30.829606';
      }

      var nonceStr = DioInterceptor.generateRandomString(20);
        options.data['nonce_str'] = nonceStr;
       var stringA = sortString(options.data);
       var stringSignTemp = "$stringA&appKey=aecdb04d";
       var sign = md5.convert(utf8.encode(stringSignTemp)).toString().toUpperCase();
        options.data['sign'] = sign;
    }
    assert((){
      Global.logger?.d('开始请求: url: ${options.path}\ndata:${options.data}\nqueryParameters:${options.queryParameters}');
      return true;
    }());

    handler.next(options);
    // super.onRequest(options, handler);
  }
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    // TODO: implement onResponse
    assert((){
      try {
        Global.logger?.d('请求回调: ${response.requestOptions.path}code:${response.statusCode}\n data:${fmt(response.data, 1)}');
      }catch (e) {
        Global.logger?.e(e,);
        Global.logger?.d('请求回调: ${response.requestOptions.path}\n data:${response.data}');
      }
      return true;
    }());

    handler.next(response);
    // super.onResponse(response, handler);
  }
  String fmt(dynamic o, int lv, {String sp = ' '}) {
    String str = '';
    String pre = sp * lv;
    if (o is Map) {
      str += '{\n';
      for (var item in o.keys) {
        str += '$pre$sp"$item":${fmt(o[item], lv + 1)},\n';
      }
      str = str.replaceRange(str.length - 2, str.length, '\n');
      str += '$pre}';
      return str;
    }
    if (o is String) {
      return '"$o"';
    }
    if (o is num) {
      return o.toString();
    }
    if (o is List) {
      str += '[';
      bool isF = true;
      for (var item in o) {
        if (isF) {
          str += '${fmt(item, lv + 1)},\n';
          isF = false;
        } else {
          str += '$pre$sp${fmt(item, lv + 1)},\n';
        }
      }
      str = str.replaceRange(str.length - 2, str.length, '\n');
      str += '$pre]';
      return str;
    }
    if (o is bool) {
      return o ? 'true' : 'false';
    }
    return 'null';
  }
   String sortString(dynamic data) {
    if (data == null) return '';
    var allKeys = data.keys.toList();
    allKeys.sort();
    var str = '';
    for (var i = 0; i < allKeys.length; i++) {
      var key = allKeys[i];
      var value = data[key];
      if (i == allKeys.length - 1) {
        str += "$key=$value";
      } else {
        str += "$key=$value&";
      }
    }
    return str;
  }
  static String generateRandomString(int length) {
    final random = Random();
    const availableChars =
        'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
    final randomString = List.generate(length,
            (index) => availableChars[random.nextInt(availableChars.length)])
        .join();

    return randomString;
  }
}